Цель исследования — исследовать рынок общепита Москвы, найти интересные особенности и презентовать полученные результаты, которые в будущем помогут в выборе подходящего места для нового заведения.
Ход исследования
Данные с заведениями общественного питания Москвы, полученные на основе данных сервисов Яндекс Карты и Яндекс Бизнес на лето 2022 года, мы получили из файла: /datasets/moscow_places.csv.
Исследование будет включать следующие этапы:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
from plotly import graph_objects as go
from folium import Map, Choropleth, Marker
import json
from folium.plugins import MarkerCluster
moscow_places = pd.read_csv('/datasets/moscow_places.csv')
display(moscow_places.head(5))
print(moscow_places.info())
В таблице 14 столбцов с различными типами данных — object и float64. Всего представлены записи о 8 406 заведениях Москвы.
Согласно документации к данным структура moscow_places.csv следующая:
Количество значений в столбцах различается. Значит, в данных есть пропущенные значения.
print(moscow_places.isna().sum())
В данных присутствуют значительные пропуски - в столбцах режима работы, категории цен и средней стоимости заказа, но заполнить их невозможно. Оставим пока все как есть.
Проверим наличие дубликатов.
print(moscow_places.duplicated().sum())
Явных дубликатов не обнаружено.
Заменим условные обозначения в столбце chain на более понятные - chain (для сетевых точек) и singlе (для единственных заведений).
moscow_places['chain'] = moscow_places['chain'].replace([0, 1], ['single', 'chain'])
Добавим столбец с указанием улицы, на которой находится заведение.
moscow_places['street'] = moscow_places['address'].str.split(',').str[1]
Добавим столбец с обозначением, что заведение работает ежедневно и круглосуточно.
moscow_places['is_24/7'] = moscow_places['hours'].str.contains('ежедневно, круглосуточно')
moscow_places.head()
В результате предобработки мы выяснили, что нам предстоит проанализировать 8406 записей о московских заведениях общепита. Каждая запись содержит информацию о названии заведения, категории, адресе и районе, часах работы, местоположении, рейтинге, категории цен, среднем чеке, принадлежности к сети и количестве мест.
Было обнаружено достаточно много пропусков в данных. В связи с невозможностью их заполнения принято решение оставить как есть. Дубликатов в данных нет. Для дальнейшего анализа добавлены стобцы с названием улицы и обозначением работы заведения 24/7.
cat = moscow_places['category'].value_counts().reset_index()
display(cat)
fig=px.bar(cat.sort_values(by='category', ascending=True), x='category', y='index', text='category')
fig.update_layout(title='Количество объектов общепита по категориям',
xaxis_title='Количество заведений',
yaxis_title='Категории')
fig.show();
В тройку самых популярных заведений Москвы вошли кафе, рестораны и кофейни. Замыкают рейтинг столовые и булочные - их почти в 10 раз меньше, чем кафе.
cat_seat = moscow_places['seats'].groupby(moscow_places['category']).median().round(1).sort_values(ascending=False).reset_index()
display(cat_seat)
fig=px.bar(cat_seat.sort_values(by='seats', ascending=True), x='seats', y='category', text='seats')
fig.update_layout(title='Медианное количество посадочных мест по категориям',
xaxis_title='Количество мест',
yaxis_title='Категории')
fig.show();
По количеству мест на первом месте по прежнему рестораны, а следом идут бары и пабы - дает о себе знать барная стойка. На последнем месте и в этом рейтинге булочные.
chain_cnt = moscow_places['chain'].value_counts().reset_index()
chain_cnt['part'] = (chain_cnt['chain']/len(moscow_places['chain'])*100).round(1)
display(chain_cnt)
fig = go.Figure(data=[go.Pie(labels=chain_cnt['index'], values=chain_cnt['chain'])])
fig.update_layout(title='Соотношение сетевых и несетевых заведений',
width=600,
height=400,
annotations=[dict(x=1.24,
y=1.1,
text='Принадлежность к сети',
showarrow=False)])
fig.show()
Несетевые заведения преобладают в Москве - 62% против 38% сетевых.
chain = moscow_places.query('chain=="chain"')
chain_cat = chain['category'].value_counts().reset_index()
display(chain_cat)
fig=px.bar(chain_cat.sort_values(by='category', ascending=True), x='category', y='index', text='category')
fig.update_layout(title='Количество сетевых объектов общепита по категориям',
xaxis_title='Количество заведений',
yaxis_title='Категории')
fig.show();
Среди сетевых заведений наиболее распространенные категории - кафе, рестораны, кофейни.
top_15_chain = chain.groupby(['name', 'category'])['address'].count().sort_values(ascending=False).reset_index().head(15)
display(top_15_chain)
plt.figure(figsize=(10, 7))
ax = sns.barplot(x='address', y='name', data=top_15_chain)
plt.title('Топ-15 популярных сетей в Москве', fontsize=15)
plt.xlabel('Количество точек', fontsize=13)
plt.ylabel('Заведения', fontsize=13);
Возглавляет топ самых распространенных московских сетей кофейня "Шоколадница", следом за ней идут две пиццерии, а также кофейни и рестораны.
Посмотрим распределение сеток по районам.
chain_dist = chain.pivot_table(index='district', columns='category', values='address', aggfunc='count')
plt.figure(figsize=(14, 7))
sns.heatmap(chain_dist, linewidths= .3, cmap='Spectral', annot=True , fmt='d', annot_kws={'size':13})
plt.title('Количество сетевых заведений каждой категории по районам', fontsize=15)
plt.xlabel('Количество точек', fontsize=13)
plt.ylabel('Районы', fontsize=13);
Самое большое скопление заведений общепита, конечно же, в центре. Здесь количество кофеен, кафе и ресторанов превышает отметку в 200 точек по каждой категории. Здесь же больше всего баров и пабов, которых в остальных районах не так и много. По графику видно, что четвертое место по количеству точек по всем районам занимают пиццерии.
total_dist = moscow_places.pivot_table(index='district', columns='category', values='address', aggfunc='count')
total_dist.plot(kind='barh', stacked=True, figsize=(9, 8))
plt.xlabel('Количество заведений', fontsize=13)
plt.ylabel('Районы', fontsize=13)
plt.legend(title = 'Категории', title_fontsize = 13)
plt.title('Количество сетевых заведений каждой категории по районам', fontsize=15);
По общему количеству заведений общепита сильно вырывается вперед Центральный АО, особенно это касается таких категорий как бары, кофейни и рестораны. Самым "негостеприимным" оказался Северо-Западный АО, хотя здесь присутствуют места из всех категорий.
cat_rate = moscow_places['rating'].groupby(moscow_places['category']).mean().round(1).sort_values(ascending=False).reset_index()
fig=px.bar(cat_rate.sort_values(by='rating', ascending=True), x='rating', y='category', text='rating')
fig.update_layout(title='Усредненный рейтинг по категориям',
xaxis_title='Рейтинг',
yaxis_title='Категории')
fig.show();
В среднем каждая категория общепита имеет рейтинг от 4 до 5 баллов. Лидируют бары и пабы с отметкой 4.4. Наименьшее значение получили фастфуды и кафе - 4.1. В остальных категориях рейтинг распределен примерно одинаково: 4.2 - 4.3.
rate_dist = moscow_places.groupby('district')['rating'].mean().round(1).sort_values(ascending=False).reset_index()
try:
state_geo = '/datasets/admin_level_geomap.geojson'
except FileNotFoundError:
state_geo = 'https://code.s3.yandex.net/data-analyst/admin_level_geomap.geojson'
moscow_lat, moscow_lng = 55.751244, 37.618423
m = Map(location=[moscow_lat, moscow_lng], zoom_start=10)
Choropleth(
geo_data=state_geo,
data=rate_dist,
columns=['district', 'rating'],
key_on='feature.name',
fill_color='BuPu',
fill_opacity=0.8,
legend_name='Средний рейтинг заведений по районам',
).add_to(m)
m
Самые высокооцениваемые заведения, ожидаемо, находятся в центре. Самый же низкий рейтинг у Северо- и Юго-Восточного АО.
moscow_lat, moscow_lng = 55.751244, 37.618423
m = Map(location=[moscow_lat, moscow_lng], zoom_start=10)
marker_cluster = MarkerCluster().add_to(m)
def create_clusters(row):
Marker(
[row['lat'], row['lng']],
popup=f"{row['name']} {row['rating']}",
).add_to(marker_cluster)
moscow_places.apply(create_clusters, axis=1)
m
top_15_street = moscow_places.groupby(['street'])['address'].count().sort_values(ascending=False).reset_index().head(15)
display(top_15_street)
top_15_street_total = moscow_places.query('street in @top_15_street["street"]')
top_15_street_cat = top_15_street_total.pivot_table(index='street', columns='category', values='address', aggfunc='count')
top_15_street_cat.plot(kind='barh', stacked=True, figsize=(9, 8))
plt.xlabel('Количество заведений', fontsize=13)
plt.ylabel('Улицы', fontsize=13)
plt.legend(title = 'Категории', title_fontsize = 13)
plt.title('Количество заведений каждой категории по топ-15 улиц', fontsize=15);
Самой "злачной" улицей Москвы оказался проспект Мира - здесь более 180 заведений общепита!
Найдем улицы, на которых находится только один объект общепита.
one_n_only = moscow_places.groupby(['street'])['address'].count().sort_values(ascending=True).reset_index()
one_n_only = one_n_only.query('address==1')
one_n_only_total = moscow_places.query('street in @one_n_only["street"]')
one_n_only_total.info()
458 улиц, где всего одно заведение! Посмотрим, какие категории представлены и размеры заведений.
one_n_only_cat = one_n_only_total['category'].value_counts().reset_index()
fig=px.bar(one_n_only_cat.sort_values(by='category', ascending=True), x='category', y='index', text='category')
fig.update_layout(title='Количество объектов общепита по категориям',
xaxis_title='Количество заведений',
yaxis_title='Категории')
fig.show();
one_n_only_cat_seat = one_n_only_total['seats'].groupby(one_n_only_total['category']).median().round(1).sort_values(ascending=False).reset_index()
fig=px.bar(one_n_only_cat_seat.sort_values(by='seats', ascending=True), x='seats', y='category', text='seats')
fig.update_layout(title='Медианное количество посадочных мест по категориям',
xaxis_title='Количество мест',
yaxis_title='Категории')
fig.show();
В основном представлены небольшие кофейни, рестораны и кафе на 40-50 посадочных мест. Самыми вместительными оказались немногочисленные столовые: медианное значение - 80 посадочных мест.
Значения средних чеков заведений хранятся в столбце middle_avg_bill. Эти числа показывают примерную стоимость заказа в рублях, которая чаще всего выражена диапазоном. Посчитайте медиану этого столбца для каждого района. Используйте это значение в качестве ценового индикатора района. Постройте фоновую картограмму (хороплет) с полученными значениями для каждого района. Проанализируйте цены в центральном административном округе и других. Как удалённость от центра влияет на цены в заведениях?
median_bill_dist = moscow_places.groupby('district')['middle_avg_bill'].median().sort_values(ascending=False).reset_index()
median_bill_dist
try:
state_geo = '/datasets/admin_level_geomap.geojson'
except FileNotFoundError:
state_geo = 'https://code.s3.yandex.net/data-analyst/admin_level_geomap.geojson'
moscow_lat, moscow_lng = 55.751244, 37.618423
m = Map(location=[moscow_lat, moscow_lng], zoom_start=10)
Choropleth(
geo_data=state_geo,
data=median_bill_dist,
columns=['district', 'middle_avg_bill'],
key_on='feature.name',
fill_color='BuPu',
fill_opacity=0.8,
legend_name='Средний чек заведений по районам',
).add_to(m)
m
Самые высокие цены в заведениях Центрального и Западного АО. А дешевле всего можно перекусить в Юго-восточном округе. Возможно, на средний чек влияет не столько расстояние до центра города, сколько престижность самого района.
В ходе исследования были проанализированы данные о 8 406 московских заведениях общепита. Выяснилось, что самыми популярными категориями являются кафе, рестораны и кофейни. Меньше всего в городе столовых и булочных.
Рейтинг вместительности несколько иной. Впереди по-прежнему рестораны, но следом идут бары и пабы. Столовые здесь на 4м месте - их хоть и немного, но посадочных мест они обеспечивают достаточно. А вот кофейни, которых в городе больше всего, оказались совсем небольшими.
Из всех заведений Москвы - только 38% относятся к сетевым. Все остальные - индивидуальные проекты. Разбивка по категориям среди сетевиков повторяет общую картину общепита - начинается с кафе, ресторанов и кофеен и заканчивается булочными и столовыми.
Среди 15 самых распространенных сетей - кофейни, пиццерии, рестораны, кафе и даже булочная. Возглавляет рейтинг кофейня "Шоколадница" - почти 120 точек по всей Москве. Больше всего сетевых заведений можно встретить в центре - более 600 кофеен, кафе и ресторанов. Здесь же больше всего баров и пабов, которых в остальных районах не так и много. Более-менее равномерно распределились по всем районам пиццерии и оказались на четвертом месте по количеству точек.
Центральный АО лидирует не только по количеству сетевых заведений, но и по общей картине тоже. Наименее заполненным оказался Северо-Западный АО.
Средний рейтинг по категориям варьируется от 4.1 у быстрого питания и кафе до 4.4 у баров и пабов. Если посмотреть на разбивку по районам, то самые высокие оценки у заведений центрального района, а самые худшие места оказались в Северо-Восточном и Юго-Восточном АО.
Самый большой выбор мест общепита на проспекте Мира - 184 заведения. Также больше 100 точек на Профсоюзной ул., пр. Вернадского и Ленинском пр.
Немало в Москве и таких улиц, где находится всего одно заведение - целых 458. В большинстве случаев это кафе, рестораны и кофейни с вместимостью до 50 гостей.
По среднему чеку к лидеру по всем параметрам Центральному АО присоединяется Западный АО. Медианное значение среднего чека по всем заведениям в этих округах составляет 1000 руб. Наименьшее значение, 450 руб., оказалось в Юго-Восточном округе. Скорее всего, этот показатель зависит от привлекательности, благоустроенности района.
Посмотрим, стоит ли открывать кофейню в таком большом городе как Москва, и как это сделать лучше всего.
Ответим на следующие вопросы:
coffee_house = moscow_places.query('category=="кофейня"')
coffee_house.info()
1413 наименований кофеен на весь город. Это немало. Посмотрим, как они расположены по районам.
moscow_lat, moscow_lng = 55.751244, 37.618423
m = Map(location=[moscow_lat, moscow_lng], zoom_start=10)
marker_cluster = MarkerCluster().add_to(m)
def create_clusters(row):
Marker(
[row['lat'], row['lng']],
popup=f"{row['name']} {row['rating']}",
).add_to(marker_cluster)
coffee_house.apply(create_clusters, axis=1)
m
coffee_house_dist = coffee_house.groupby('district')['category'].count().sort_values(ascending=False).reset_index()
coffee_house_dist
try:
state_geo = '/datasets/admin_level_geomap.geojson'
except FileNotFoundError:
state_geo = 'https://code.s3.yandex.net/data-analyst/admin_level_geomap.geojson'
moscow_lat, moscow_lng = 55.751244, 37.618423
m = Map(location=[moscow_lat, moscow_lng], zoom_start=10)
Choropleth(
geo_data=state_geo,
data=coffee_house_dist,
columns=['district', 'category'],
key_on='feature.name',
fill_color='BuPu',
fill_opacity=0.8,
legend_name='Распределение кофеен по районам',
).add_to(m)
m
Почти треть всех кофеен Москвы сосредоточена в Центральном АО. Открыть здесь конкурентноспособную кофейню будет крайне сложно. Стоит рассмотреть другие районы.
Рассмотрим режим работы.
coffee_house['is_24/7'].value_counts()
Всего 59 кофеен работают ежедневно и круглосуточно. Придется попотеть, чтобы отыскать вкусный и свежий кофе посреди ночи или в выходной.
Интересно, как высоко посетители кофеен оценивают места своего досуга?
coffee_house_rate = coffee_house.groupby('district')['rating'].mean().round(2).sort_values(ascending=False).reset_index()
coffee_house_rate
try:
state_geo = '/datasets/admin_level_geomap.geojson'
except FileNotFoundError:
state_geo = 'https://code.s3.yandex.net/data-analyst/admin_level_geomap.geojson'
moscow_lat, moscow_lng = 55.751244, 37.618423
m = Map(location=[moscow_lat, moscow_lng], zoom_start=10)
Choropleth(
geo_data=state_geo,
data=coffee_house_rate,
columns=['district', 'rating'],
key_on='feature.name',
fill_color='BuPu',
fill_opacity=0.8,
legend_name='Распределение рейтинга кофеен по районам',
).add_to(m)
m
Ссылаясь на данное исследование, можно заявить, что в Западом АО подают худший кофе в столице. А согласно проведенному выше анализу средний чек здесь не отстает от заведений центрального района. Хотя, возможно, у местных жителей слегка завышены ожидания.
Посмотрим внимательнее, как разнится стоимость капучино от района к району.
coffee_house_cup = coffee_house.groupby('district')['middle_coffee_cup'].median().round(1).sort_values(ascending=False).reset_index()
coffee_house_cup
try:
state_geo = '/datasets/admin_level_geomap.geojson'
except FileNotFoundError:
state_geo = 'https://code.s3.yandex.net/data-analyst/admin_level_geomap.geojson'
moscow_lat, moscow_lng = 55.751244, 37.618423
m = Map(location=[moscow_lat, moscow_lng], zoom_start=10)
Choropleth(
geo_data=state_geo,
data=coffee_house_cup,
columns=['district', 'middle_coffee_cup'],
key_on='feature.name',
fill_color='BuPu',
fill_opacity=0.8,
legend_name='Средняя стоимость чашки капучино по районам',
).add_to(m)
m
Неожиданно на юго-западе оказался самый дорогой кофе в Москве.
В Москве уже достаточно много кофеен и оказаться очередной забегаловкой по дороге на работу или окошком с кофе на вынос довольно легко. Но чтобы открыть действительно крутое место, куда люди будут идти за атмосферой и настроением, сопровождающимися приятными напитками, нужно постараться.
С точки зрения расположения не стоит присоединяться к масштабным скоплениям заведений. Да, там, возможно, бОльшая проходимость, но и очень сильный уровень конкуренции. Недостаток кофеен ощущается в следующих районах: Восточный, Юго-Западный, Юго-Восточный и Северо-Западный АО. По качеству страдают Юго-Восточный, Южный, Северо-Восточный и Западный.
Желательно более точно определить ЦА - примерный возраст, уровень дохода, статус занятости и семейное положение. Если же ориентироваться на "Друзей", то это молодые специалисты 30-35 лет.
По стоимости стоит обратить внимание на северные округа - здесь чашка капучино не так дорога, как в Западном и Центральном районах (от 190 руб. и выше), и не такая дешевая как на юге и востоке (меньше 150 руб.). Медианное значение колеблется в пределах 159-165 рублей. Слишком высокую цену не все посетители будут готовы платить, а слишком низкая заставит сомневаться в качестве напитка.
Выбирая из северных районов снова обратимся к количеству и рейтингам. В Северном АО достаточно много кофеен, этот район занимает второе место после центра. Оценка качества у этих точек тоже достаточно высока - 4.29.
Сравним Северо-Восток и Северо-Запад. У первого много заведений, но низкий рейтинг, а у второго все наоборот - кофеен немного, но рейтинг достаточно высок (лучший после центра).
В первом случае рискуем "смешаться с толпой" и показаться очередной невкусной и неудобной точкой. Необходимо будет приложить много усилий, чтобы убедить потенциальных посетителей в том, что именно эта кофейня превзойдет их ожидания и станет любимым местом встреч с друзьями.
Если выбрать Северо-Запад, то здесь надо не полениться, продумать все детали и открыть действительно крутое место, чтобы не отставать от соседей с высоким рейтингом. Также необходимо будет провести дополнительное исследование района и внимательно выбрать место для кофейни, чтобы не оказаться рядом с лесом или промзоной с малой проходимостью.
Дополнительный совет - если найти место рядом с развлекательными точками или вблизи баров, то можно подумать о режиме работы 24/7.
Презентация: https://disk.yandex.ru/i/l3Q2THq-p7iweA